"""
话术文本处理工具类
负责处理话术文本的各种操作，包括变量替换、文本清理等功能
"""
import re
import os
import random
import datetime
from typing import Dict, Any, Optional, List


class SpeechTextProcessor:
    """
    话术文本处理工具类
    负责处理话术文本的各种操作，包括变量替换、文本清理等功能
    """
    
    @staticmethod
    def process_speech(text: str, variables: Optional[Dict[str, Any]] = None) -> str:
        """
        处理话术文本，一次性完成所有处理操作，请优先调用这个方法
        包括变量替换和随机文本处理
        
        @param text: 原始话术文本
        @param variables: 变量字典，如果为None则只替换内置变量
        @return: 处理后的文本
        """
        if not text:
            return text
            
        # 先替换变量
        result = SpeechTextProcessor.replace_variables(text, variables)
        
        # 再处理随机文本（因为变量替换可能会引入新的随机文本格式）
        result = SpeechTextProcessor.process_random_text(result)
        
        return result
    
    @staticmethod
    def replace_variables(text: str, variables: Optional[Dict[str, Any]] = None) -> str:
        """
        替换话术中的变量
        
        @param text: 原始话术文本
        @param variables: 变量字典，如果为None则只替换内置变量
        @return: 替换后的文本
        """
        if not text:
            return text
            
        # 创建一个结果文本的副本
        result = text
        
        # 替换内置变量
        now = datetime.datetime.now()
        
        # 随机选择"日"或"号"
        day_suffix = random.choice(["日", "号"])
        
        # 替换时间相关变量
        result = result.replace("{当前时间}", now.strftime("%H点%M分"))
        result = result.replace("{当前日期}", f"{now.year}年{now.month}月{now.day}{day_suffix}")
        result = result.replace("{当前年}", str(now.year))
        result = result.replace("{当前月}", str(now.month))
        result = result.replace("{当前日}", str(now.day))
        result = result.replace("{星期}", ["一", "二", "三", "四", "五", "六", "日"][now.weekday()])
        
        # 替换自定义变量
        if variables:
            for key, value in variables.items():
                placeholder = "{" + key + "}"
                if placeholder in result:
                    result = result.replace(placeholder, str(value))
        
        return result
    
    @staticmethod
    def process_random_text(text: str) -> str:
        """
        处理随机文本选项，将形如{选项1|选项2|选项3}的文本替换为随机选择的一个选项
        
        @param text: 原始文本
        @return: 处理后的文本
        """
        if not text:
            return text
            
        # 创建结果文本的副本
        result = text
        
        # 处理嵌套的花括号，从内到外
        # 使用正则表达式查找最内层的花括号（不包含其他花括号的花括号）
        pattern = r'\{([^{}]*\|[^{}]*)\}'
        
        # 循环处理所有匹配项，直到没有更多匹配
        while re.search(pattern, result):
            # 查找当前最内层的花括号
            matches = re.finditer(pattern, result)
            
            # 创建一个新的结果字符串，逐步替换匹配项
            new_result = result
            offset = 0  # 用于跟踪替换后的位置偏移
            
            for match in matches:
                # 获取匹配的完整文本和选项部分
                start, end = match.span()
                start += offset  # 调整起始位置
                end += offset    # 调整结束位置
                
                full_match = match.group(0)  # 例如：{你好|你来啦|哈喽}
                options_text = match.group(1)  # 例如：你好|你来啦|哈喽
                
                # 分割选项
                options = options_text.split('|')
                
                # 随机选择一个选项
                if options:
                    chosen_option = random.choice(options)
                    # 替换原文本
                    new_result = new_result[:start] + chosen_option + new_result[end:]
                    # 更新偏移量
                    offset += len(chosen_option) - (end - start)
                else:
                    # 如果没有有效选项，则移除整个匹配
                    new_result = new_result[:start] + new_result[end:]
                    # 更新偏移量
                    offset -= (end - start)
            
            # 更新结果
            result = new_result
        
        return result
    
    @staticmethod
    def sanitize_filename(filename: str) -> str:
        """
        清理文件名，替换不符合文件名规则的字符
        
        @param filename: 原始文件名
        @return: 清理后的文件名
        """
        # 处理None值
        if filename is None:
            return "speech"
            
        # 替换不允许的字符为下划线
        # Windows文件名不允许包含以下字符: \ / : * ? " < > |
        sanitized = re.sub(r'[\\/:*?"<>|]', '_', filename)
        
        # 去除前后空白字符
        sanitized = sanitized.strip()
        
        # 如果文件名为空，使用默认名称
        if not sanitized:
            sanitized = "speech"
        
        return sanitized
    
    @staticmethod
    def clean_text(text: str) -> str:
        """
        清理文本，去除多余空格、特殊字符等
        
        @param text: 原始文本
        @return: 清理后的文本
        """
        if not text:
            return ""
            
        # 去除前后空白
        cleaned = text.strip()
        
        # 将多个空格替换为单个空格
        cleaned = re.sub(r'\s+', ' ', cleaned)
        
        return cleaned
    
    @staticmethod
    def extract_speech_name(filename: str) -> str:
        """
        从文件名中提取话术名称
        支持以下格式：
        1. 纯数字格式：1.0.txt
        2. 带花括号的格式：3.0{停顿}.txt
        3. 带后缀的格式：6.1人数时间.txt
        
        @param filename: 文件名
        @return: 话术名称
        """
        # 移除扩展名
        name = os.path.splitext(filename)[0]
        
        # 尝试提取花括号中的内容或后缀
        match = re.search(r'^\d+\.\d+(?:\{([^}]+)\}|([^{}.]+))?$', name)
        if match:
            # 如果有花括号内容或后缀，返回它
            return match.group(1) or match.group(2) or name
        
        # 如果没有匹配，返回原始名称
        return name
    
    @staticmethod
    def get_sort_key(filename: str) -> float:
        """
        从文件名中提取排序键
        支持以下格式：
        1. 纯数字格式：1.0.txt
        2. 带花括号的格式：3.0{停顿}.txt
        3. 带后缀的格式：6.1人数时间.txt
        
        @param filename: 文件名
        @return: 排序键（浮点数）
        """
        try:
            # 提取文件名中的数字部分
            match = re.match(r'^(\d+\.\d+)', filename)
            if match:
                return float(match.group(1))
        except (ValueError, IndexError, AttributeError):
            pass
        
        # 如果无法提取排序键，则返回一个很大的数，使其排在最后
        return float('inf')
    
    @staticmethod
    def format_ai_reply(text: str) -> str:
        """
        格式化AI回复文本，去除特殊字符，规范格式
        
        @param text: 原始AI回复文本
        @return: 格式化后的文本
        """
        if not text:
            return ""
            
        # 去除前后空白
        formatted = text.strip()
        
        # 去除花括号，避免与变量替换冲突
        formatted = formatted.replace('{', '').replace('}', '')
        
        # 将多个空格替换为单个空格
        formatted = re.sub(r'\s+', ' ', formatted)
        
        return formatted
    
    @staticmethod
    def truncate_text(text: str, max_length: int = 100, suffix: str = "...") -> str:
        """
        截断文本，超过最大长度时添加后缀
        
        @param text: 原始文本
        @param max_length: 最大长度
        @param suffix: 截断后添加的后缀
        @return: 截断后的文本
        """
        if not text or len(text) <= max_length:
            return text
            
        return text[:max_length] + suffix